package org.litu.app.controller.system;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.lang3.StringUtils;
import org.litu.app.constant.SysContant;
import org.litu.app.entity.system.SysFiles;
import org.litu.app.service.ISysFilesService;
import org.litu.base.controller.BaseFormController;
import org.litu.base.log.LtLog;
import org.litu.base.log.LtLogOperation;
import org.litu.base.log.LtLogOperationEnum;
import org.litu.core.base.ApiRes;
import org.litu.core.enums.ResultEnum;
import org.litu.core.exception.LtParamException;
import org.litu.core.login.TokenCheck;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.Map;


/**
 * 文件管理表 前端控制器
 *
 * @author ltgk
 * @since 2019-12-09
 */
@RestController
@LtLog(module = "系统附件表")
@RequestMapping("/system/sysFiles")
@Api(value = "系统附件表", tags = {"系统附件表"}, protocols = "http,https")
public class SysFilesController extends BaseFormController<SysFiles, ISysFilesService> {

    /**
     * 上传文件
     *
     * @param file 要上传的文件
     * @return 成功则返回提交成功和相应信息
     */
    @PostMapping("/upload")
    @LtLogOperation(operation = LtLogOperationEnum.UPLOAD)
    @ApiOperation(value = "文件上传", notes = "文件上传到服务器，返回上传文件的信息。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "file", value = "文件信息", required = true, dataType = "file")
    })
    public ApiRes uploadFile(@RequestParam("file") MultipartFile file) {
        if (file.isEmpty()) {
            return ApiRes.error(ResultEnum.ParamError, "文件不能为空!");
        }

        SysFiles result = service.uploadFile(nowUser(), null, file);
        if (result == null) {
            return ApiRes.error(ResultEnum.UpdateError, "文件上传失败!");
        }
        return ApiRes.ok(result);
    }

    /************************  文件加载和下载的方法  ***********************/

    /**
     * 加载文件通过id
     *
     * @param fileId 要加载的文件id
     */
    @GetMapping(value = "/loadById")
    @ApiOperation(value = "文件加载依据文件ID", notes = "根据文件ID加载文件信息。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileId", value = "文件ID", required = true),
    })
    @TokenCheck(check = false)
    public void loadFileById(@RequestParam(name = "fileId") String fileId) {
        if (StringUtils.isBlank(fileId)) {
            throw new LtParamException("文件信息不能为空!");
        }
        SysFiles fileObj = service.getById(fileId);
        service.load(fileObj.getLocation(), response);
    }

    /**
     * 分段加载文件通过id
     * 文件实现分段加载。
     *
     * @param fileId 要加载的文件id
     */
    @GetMapping(value = "/loadRangeById")
    @ApiOperation(value = "文件加载依据文件ID", notes = "根据文件ID加载文件信息,文件实现分段加载。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileId", value = "文件ID", required = true),
    })
    @TokenCheck(check = false)
    public void loadRangeById(@RequestParam(name = "fileId") String fileId) {
        if (StringUtils.isBlank(fileId)) {
            throw new LtParamException("文件信息不能为空!");
        }
        SysFiles fileObj = service.getById(fileId);
        service.loadRange(fileObj.getLocation(), request, response);
    }

    /**
     * 获取缩略图，仅限于图片，非图片将会返回空
     *
     * @param fileId 要加载的文件id
     */
    @GetMapping(value = "/loadThumbnailById")
    @ApiOperation(value = "获取缩略图", notes = "获取缩略图，仅限于图片，非图片将会返回空。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileId", value = "文件ID", required = true),
    })
    @TokenCheck(check = false)
    public void loadThumbnailById(@RequestParam(name = "fileId") String fileId) {
        if (StringUtils.isBlank(fileId)) {
            throw new LtParamException("文件信息不能为空!");
        }
        SysFiles fileObj = service.getById(fileId);
        // 如果启动了获取缩略图，才进行缩略图返回，否则返回原图
        if (SysContant.THUMBNAIL_IMAGE) {
            service.loadThumbnail(fileObj.getFileType(), fileObj.getLocation(), response);
        } else {
            service.load(fileObj.getLocation(), response);
        }
    }

    /**
     * 下载文件通过Id
     *
     * @param fileId 文件Id
     */
    @GetMapping("/downloadById")
    @ApiOperation(value = "文件下载，依据文件ID", notes = "根据文件ID下载文件信息。")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "fileId", value = "文件ID", required = true),
    })
    @TokenCheck(check = false)
    public void downloadById(@RequestParam(name = "fileId") String fileId) {
        if (StringUtils.isBlank(fileId)) {
            throw new LtParamException("文件信息不能为空!");
        }
        SysFiles fileObj = service.getById(fileId);
        String filePath = fileObj.getLocation();
        service.download(filePath, fileObj.getOriginName(), response);
    }

    /************************  业务处理方法  ***********************/

    /**
     * 根据文件ID获取文件的名称
     *
     * @param ids 要获取名称的文件的ID信息
     * @return
     */
    @GetMapping("/getNameByIds")
    @LtLogOperation(enable = false)
    @ApiOperation(value = "根据ID信息获取文件的名称", notes = "根据文件ID获取文件名称")
    @ApiImplicitParam(name = "ids", value = "ID如果为一个直接传即可，多个ID使用都好隔开,返回值为字符串数组", required = true, dataType = "file")
    public ApiRes getNameByIds(@RequestParam(name = "ids") String ids) {
        if (StringUtils.isBlank(ids)) {
            return ApiRes.error(ResultEnum.ParamError, "参数部门为空");
        }
        String[] idArr = ids.split(",");

        Map<String, String> fileNames = service.getNameByIds(idArr);

        return ApiRes.ok(fileNames);
    }

    /**
     * 根据系统中文件的使用情况，对未使用到的所有文件进行清理
     */
    @PostMapping(value = "/clearNoUse")
    @LtLogOperation(operation = LtLogOperationEnum.DELETE)
    @ApiOperation(value = "无用文件清理", notes = "根据系统中文件的使用情况，对未使用到的所有文件进行清理")
    public ApiRes clearNoUse() {
        try {
            List<SysFiles> files = service.clearNoUse();

            return ApiRes.ok(files.size());
        } catch (Exception e) {
            logger.error("文件删除执行错误", e);
            return ApiRes.error(ResultEnum.ServerError, "文件删除执行错误");
        }
    }
}